/**
 * 异常处理工具类
 */
package dragon.core.exception;

import java.io.PrintWriter;
import java.io.StringWriter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import dragon.core.db.DBUtil;
import dragon.core.db.DBUtil.DatabaseProduct;
import dragon.core.util.StringUtils;

public class ExceptionHandler extends Exception {

	private Logger logger = LoggerFactory.getLogger(ExceptionHandler.class);

	private static final long serialVersionUID = 8814450710415383549L;

	public ExceptionHandler(String arg0) {
		super(arg0);
		deal(arg0, null);
	}

	public ExceptionHandler(Throwable arg1) {
		super(arg1);
		deal(null, arg1);
	}

	public ExceptionHandler(String arg0, Throwable arg1) {
		super(arg0, arg1);
		deal(arg0, arg1);
	}

	private void deal(String arg0, Throwable arg1) {
		logger.error(arg0, arg1);
		if (arg1 != null) {
			if (arg1.getCause() == null) {
				return;
			}
			String className = arg1.getCause().getClass().getName();
			String message = arg1.getMessage();

			// 是否需要重新连接数据库
			boolean needConnectDB = false;
			try {
				if (DatabaseProduct.Oracle.equals(DBUtil.getDatabaseProduct())) {
					if ("java.sql.SQLException".equals(className)) {
						if (!StringUtils.isEmpty(message) && message.contains("关闭的连接")) {
							needConnectDB = true;
						}
					}
				} else if (DatabaseProduct.PostgreSQL.equals(DBUtil.getDatabaseProduct())) {
					if ("org.postgresql.util.PSQLException".equals(className)) {
						if (!StringUtils.isEmpty(message) && message.contains("传送数据至后端时发生 I/O 错误")) {
							needConnectDB = true;
						}
					}
				}
			} catch (ExceptionHandler e2) {
				logger.error(e2.getMessage(), e2);
			}
			if (needConnectDB) {
				while (true) {
					logger.info("尝试重新连接数据库...");
					try {
						DBUtil.getDatabase(true);
						logger.info("已重新连接数据库！");
						break;
					} catch (ExceptionHandler e) {
						logger.info("未能连接到数据库，等待30秒后重新尝试...");
						try {
							Thread.sleep(30000);// 隔30秒再次尝试
						} catch (InterruptedException e1) {
							logger.error(e1.getMessage(), e1);
						}
					}
				}
			}

		}
	}

	public static String paraseException(Exception e) {
		StringWriter writer = new StringWriter();
		e.printStackTrace(new PrintWriter(writer));
		String errors = writer.getBuffer().toString();
		return errors;
	}

}
